import pandas as pd
import matplotlib.pyplot as plt

# ---------------------- 1. 数据读取与预处理 ----------------------
# 读取Excel成绩数据（假设文件名为"学生成绩表.xlsx"，工作表为"成绩记录"）
df = pd.read_excel("学生各学期成绩表.xlsx",)

# 提取语文、数学、英语三科成绩，并删除可能的缺失值
subjects = ["语文", "数学", "英语"]
df_subjects = df[subjects].dropna()  # 仅保留三科数据，删除含空值的行

# 检查数据是否有效（可选，用于验证）
print("有效考试次数：", len(df_subjects))
print("三科成绩预览：")
print(df_subjects.head())

# ---------------------- 2. 统计分析（进阶要求） ----------------------
# 计算三科成绩的标准差（判断波动程度：值越小越稳定）
std_scores = df_subjects.std()
print("\n三科成绩标准差（波动程度）：")
print(std_scores)

# 统计110分及以上的次数（高分表现）
high_score_counts = (df_subjects >= 110).sum()  # 每科>=110的次数求和
print("\n三科110分及以上的考试次数：")
print(high_score_counts)

# ---------------------- 3. 绘图设置 ----------------------
# 解决中文显示问题
plt.rcParams["font.sans-serif"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False  # 解决负号乱码

# 统一设置成绩区间（90-120分，每5分一个区间）
bins = [90, 95, 100, 105, 110, 115, 120]

# 三科颜色（蓝、红、绿）和标题
colors = ["#1f77b4", "#ff7f0e", "#2ca02c"]
titles = ["语文成绩分布", "数学成绩分布", "英语成绩分布"]

# ---------------------- 4. 绘制多子图直方图 ----------------------
# 创建1行3列的子图，设置画布大小
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5), dpi=100)
axes = [ax1, ax2, ax3]  # 子图列表，便于循环处理

for i in range(3):
    # 绘制当前学科的直方图，获取返回值（次数、区间、柱子对象）
    n, bins_edges, patches = axes[i].hist(
        df_subjects[subjects[i]],  # 数据：当前学科成绩
        bins=bins,  # 区间：统一分箱
        color=colors[i],  # 颜色：学科对应颜色
        edgecolor="black",  # 柱子边缘色：黑色
        alpha=0.7  # 透明度：0.7（避免过深）
    )

    # 标记高分区间（110分及以上的柱子添加斜线）
    for j in range(len(patches)):
        # 区间左边界>=110时，判定为高分区间
        if bins_edges[j] >= 110:
            patches[j].set_hatch("//")  # 添加斜线填充

    # 设置子图细节
    axes[i].set_title(titles[i], fontsize=12, pad=10)  # 标题
    axes[i].set_xlabel("成绩/分", fontsize=10)  # x轴标签
    axes[i].set_ylabel("考试次数", fontsize=10)  # y轴标签
    axes[i].grid(axis="y", alpha=0.3, linestyle="--")  # y轴网格线
    axes[i].set_xticks(bins)  # x轴刻度与区间对齐，更直观

# ---------------------- 5. 调整布局并显示 ----------------------
plt.tight_layout()  # 自动调整子图间距，避免标签重叠
plt.show()

# ---------------------- 6. 结果分析（可作为提交时的文字说明） ----------------------
print("\n分析结论：")
print(f"1. 成绩最稳定的学科是：{std_scores.idxmin()}（标准差最小：{std_scores.min():.2f}）")
print(f"2. 高分（110分及以上）出现次数最多的学科是：{high_score_counts.idxmax()}（共{high_score_counts.max()}次）")